namespace classifier_test
{

namespace high_order
{

class concept_cleaner : public virtual virtual_object, private noncopyable
{
public:
	struct chunk
	{
		int begin, end;
		int concept;
	};
	struct concept
	{
		smart_ptr<validation_dataset> vdataset;
		smart_ptr<validation_classifier> vclassifier;
		double verror;
	};

	concept_cleaner();
	concept_cleaner(const concept_cleaner& Val);
	virtual smart_ptr<concept_cleaner> clone() const = 0;
	virtual void serialize(serializer& Serializer);
	virtual void initialize_options(command_line_options& Options) const;
	virtual void apply_arguments(const command_line_arguments& Args);

	virtual void set_chunk_count(int Val) = 0;
	virtual void set_chunk(int I, int Begin, int End, int Concept) = 0;
	virtual void set_concept_count(int Val) = 0;
	virtual void set_concept(int I, smart_ptr<validation_dataset> VDataset, smart_ptr<validation_classifier> VClassifier, double VError) = 0;
	virtual void compute() = 0;
	virtual int get_chunk_count() const = 0;
	virtual const chunk& get_chunk(int I) const = 0;
	virtual int get_concept_count() const = 0;
	virtual const concept& get_concept(int I) const = 0;
};

class high_order_concept_cleaner : public concept_cleaner
{
public:
	high_order_concept_cleaner();
	high_order_concept_cleaner(const high_order_concept_cleaner& Val);
	smart_ptr<concept_cleaner> clone() const;
	void serialize(serializer& Serializer);
	void initialize_options(command_line_options& Options) const;
	void apply_arguments(const command_line_arguments& Args);
	double get_error_threshold() const;
	void set_error_threshold(double Val);

	void set_chunk_count(int Val);
	void set_chunk(int I, int Begin, int End, int Concept);
	void set_concept_count(int Val);
	void set_concept(int I, smart_ptr<validation_dataset> VDataset, smart_ptr<validation_classifier> VClassifier, double VError);
	void compute();
	int get_chunk_count() const;
	const chunk& get_chunk(int I) const;
	int get_concept_count() const;
	const concept& get_concept(int I) const;

private:
	struct my_concept : public concept
	{
		int index;
	};
	struct my_chunk : public chunk
	{
		my_concept* concept_ptr;
	};

	double ErrThreshold;
	vector<my_chunk> Chunks;
	vector<smart_ptr<my_concept> > Concepts;

	void clean();
	void group_chunks_by_concepts();

	void replace_concept(my_concept* Old, my_concept* New, double Err);
	void remove_concept(my_concept* Con);
};

}

}
